#pragma once

#include <iostream>
#include <string>
#include <unordered_map>
#include "Socket.hpp"
#include "Connection.hpp"
#include "Epoller.hpp"

using namespace EpollerModule;

#define EPOLL_BLOCK -1

class TcpServer;

// 只要管理一堆的Connection, 它就是Reactor！
// class Reactor --- 核心的部分
class TcpServer
{
    static const int gmaxevents = 64;

public:
    TcpServer() : _isrunning(false), _timeout(EPOLL_BLOCK)
    {
        _epoller.InitEpoller();
    }
    bool IsConnectionExists(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        if (iter == _connections.end())
            return false;
        else
            return true;
    }
    void AddConnection(Connection *conn)
    {
        if (!conn)
            return;
        if (IsConnectionExists(conn->SockFd()))
            return;
        // 1. 添加TcpServer unordered_map
        _connections.insert(std::make_pair(conn->SockFd(), conn));
        lg.LogMessage(Info, "add a new connection success, sockfd: %d\n", conn->SockFd());
        // 2. 让epoller管理起来
        _epoller.AddEvent(conn->SockFd(), conn->Events());
    }
    void EnableReadWrite(int sockfd, bool readable, bool writeable)
    {
        if (!IsConnectionExists(sockfd))
            return;
        uint32_t events = ((readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0) | EPOLLET);
        // 1. 修改connection自己关心的事件
        _connections[sockfd]->SetEvents(events);
        // 2. 修改epoller, 写透到内核
        _epoller.ModEvent(sockfd, _connections[sockfd]->Events());
    }
    void RemoveConnection(int sockfd)
    {
        if (!IsConnectionExists(sockfd))
            return;
        // 1. 清理connection自己关心的事件
        _connections[sockfd]->SetEvents(0);
        // 2. 清理epoller中对于sockfd的关心, 写透到内核
        _epoller.DelEvent(sockfd);
        // 3. 移除在_connections中的key value
        _connections.erase(sockfd);
    }
    void LoopOnce(int timeout) // 事件派发
    {
        int n = _epoller.Wait(_revs, gmaxevents, timeout);
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revs[i].data.fd;
            uint32_t events = _revs[i].events;

            // 将所有的epoll检测到的fd的问题，最后统一转换成为读写错误
            if (events & EPOLLERR)
                events |= (EPOLLIN | EPOLLOUT);
            if (events & EPOLLHUP)
                events |= (EPOLLIN | EPOLLOUT);
            // 未来所有的IO操作，都会转化成为下面的部分
            // 整个代码有没有执行IO代码？没有！
            // IO代码将来在哪里？？？connection的回调中.
            // 我们在干什么？？？事件派发
            if ((events & EPOLLIN) && IsConnectionExists(sockfd)) // 细节
            {
                if (_connections[sockfd]->_recver)
                    _connections[sockfd]->_recver(_connections[sockfd]);
            }
            if ((events & EPOLLOUT) && IsConnectionExists(sockfd))
            {
                if (_connections[sockfd]->_sender)
                    _connections[sockfd]->_sender(_connections[sockfd]);
            }
        }
    }
    void Dispatcher() // 事件派发器
    {
        _isrunning = true;
        while (_isrunning)
        {
            _epoller.DebugFdList();
            LoopOnce(_timeout); // 事件派发
            // 对其他事情进行处理
        }
        _isrunning = false;
    }
    ~TcpServer()
    {
    }

private:
    Epoller _epoller;
    struct epoll_event _revs[gmaxevents];
    int _timeout;
    std::unordered_map<int, Connection *> _connections;
    bool _isrunning;

    // std::vector<func_t> others;
};